<template>
  <div class="case-edit">

    <div class="case-edit-api-info">
      <h3 class="api-title"> 步骤信息</h3>
      <el-form ref="form" label-width="100px">
        <el-row>
          <el-col :span="11">
            <el-form-item label="步骤编号" required>
              <el-input placeholder="步骤编号" v-model="caseStepForm.id" :disabled="true">
              </el-input>
            </el-form-item>
          </el-col>

          <el-col :span="12" :offset="1">
            <el-form-item label="步骤名称" required>
              <el-input placeholder="步骤名称" v-model="caseStepForm.name">
              </el-input>
            </el-form-item>
          </el-col>

          <el-col :span="11">
            <el-form-item label="接口分组">
              <el-select v-model="caseStepForm.groupId" placeholder="请选择分组" @change="handleChange(caseStepForm.groupId)">
                <el-option v-for="item in groupList" :key="item.groupId" :label="item.name" :value="item.groupId">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>

          <el-col :span="12" :offset="1">
            <el-form-item label="接口名称">
              <el-select v-model="caseStepForm.apiId" placeholder="请选择接口" @change="handleChangeApi(caseStepForm.apiId)">
                <el-option v-for="item in apiList" :key="item.id" :label="item.name + item.path " :value="item.id">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>

          <el-col :span="11">
            <el-form-item label="优先级别">

              <el-select v-model="caseStepForm.priority" placeholder="请选择">
                <el-option label="P1" value="P1"></el-option>
                <el-option label="P2" value="P2"></el-option>
                <el-option label="P3" value="P3"></el-option>
                <el-option label="P4" value="P4"></el-option>
                <el-option label="P5" value="P5"></el-option>
              </el-select>

            </el-form-item>
          </el-col>

          <el-col :span="12" :offset="1">
            <el-form-item label="添加人员">
              <el-input placeholder="接口路径" v-model="caseStepForm.userName">
              </el-input>

            </el-form-item>
          </el-col>
          <el-col :span="11">
            <el-form-item label="用例标签">
              <el-select multiple filterable allow-create default-first-option placeholder="请选择文章标签" v-model="caseStepForm.label">
                <el-option label="冒烟" value="冒烟"></el-option>
                <el-option label="回归" value="回归"></el-option>
                <el-option label="功能" value="功能"></el-option>
              </el-select>
            </el-form-item>

          </el-col>

          <el-col :span="12" :offset="1">
            <el-form-item label="步骤类型">
              <el-select v-model="caseStepForm.type" placeholder="请选择">
                <el-option label="API" value="API"></el-option>
                <el-option label="JDBC" value="JDBC"></el-option>
                <el-option label="UI" value="UI"></el-option>
              </el-select>

            </el-form-item>
          </el-col>

        </el-row>

      </el-form>

    </div>

    <div>
      <h3 class="api-title"> Request</h3>
      <div style="margin-bottom:20px">
        <el-input placeholder="请输入路径" v-model="apiForm.path" class="input-with-select">
          <el-select v-model="apiForm.protocol" slot="prepend" placeholder="请选择" class="api-debug-select">
            <el-option label="http" value="http"></el-option>
            <el-option label="https" value="https"></el-option>
          </el-select>
          <el-select v-model="caseStepForm.envId" slot="prepend" placeholder="请选择环境" class="api-debug-select-1" style="border-left: 1px solid #dcdfe6;">
            <el-option v-for="(item,index) in envList.list" :value="item.id" :key="index" :label="item.host +':'+ item.port"></el-option>
          </el-select>
          <!-- <el-button slot="append" type="primary" @click="debugApiExecute(apiForm)"><i class="el-icon-caret-right"></i>调试</el-button> -->
        </el-input>
      </div>

      <div class="api-debug-request-params">
        <div class="interface-tab">
          <el-tabs v-model="activeName" class="interface-edit interface-tab-in">

            <el-tab-pane label="请求参数" name="first">
              <div class="interface-edit-tabs">
                <el-button type="primary" size="mini" icon="el-icon-plus" @click="addNewParams()">添加</el-button>
                <el-row v-for="(item,index) in parameters" :key="index">
                  <el-col :span="8">
                    <el-input placeholder="参数名" v-model="item.name"></el-input>
                  </el-col>
                  <el-col :span="12">
                    <el-input placeholder="参数值" v-model="item.value"></el-input>
                  </el-col>
                  <el-col :span="4">
                    <el-button type="primary" size="mini" icon="el-icon-plus" circle @click="addNewParams()"></el-button>
                    <el-button type="danger" size="mini" icon="el-icon-delete" circle v-on:click="parameters.splice(index,1)"></el-button>
                  </el-col>
                </el-row>
              </div>

            </el-tab-pane>

            <el-tab-pane label="Header" name="second">
              <div class="interface-edit-tabs">
                <el-button type="primary" size="mini" icon="el-icon-plus" @click="addNewHeaders()">添加</el-button>
                <el-row v-for="(item,index) in headers" :key="index">
                  <el-col :span="8">
                    <el-input placeholder="参数名" v-model="item.name"></el-input>
                  </el-col>

                  <el-col :span="12">
                    <el-input placeholder="参数值" v-model="item.value"></el-input>
                  </el-col>
                  <el-col :span="4">
                    <el-button type="primary" size="mini" icon="el-icon-plus" circle @click="addNewHeaders()"></el-button>
                    <el-button type="danger" size="mini" icon="el-icon-delete" circle v-on:click="headers.splice(index,1)"></el-button>
                  </el-col>
                </el-row>
              </div>

            </el-tab-pane>

            <el-tab-pane label="Cookie" name="third">
            </el-tab-pane>

            <el-tab-pane label="前置处理" name="fourth">
              <div class="interface-edit-tabs">
                <el-button type="primary" size="mini" icon="el-icon-plus" @click="addNewPreProcessing()">添加</el-button>
                <el-row v-for="(item,index) in preProcessing" :key="index">
                  <el-col :span="8">
                    <el-input placeholder="参数名" v-model="item.name"></el-input>
                  </el-col>
                  <el-col :span="12">
                    <el-input placeholder="参数值" v-model="item.value"></el-input>
                  </el-col>
                  <el-col :span="4">
                    <el-button type="primary" size="mini" icon="el-icon-plus" circle @click="addNewPreProcessing()"></el-button>
                    <el-button type="danger" size="mini" icon="el-icon-delete" circle v-on:click="preProcessing.splice(index,1)"></el-button>
                  </el-col>
                </el-row>

              </div>

            </el-tab-pane>
            <el-tab-pane label="后置处理" name="five">
              <div class="interface-edit-tabs">
                <el-button type="primary" size="mini" icon="el-icon-plus" @click="addNewPostProcessing()">添加</el-button>
                <el-row v-for="(item,index) in postProcessing" :key="index">
                  <el-col :span="8">
                    <el-input placeholder="参数名" v-model="item.name"></el-input>
                  </el-col>
                  <el-col :span="12">
                    <el-input placeholder="参数值" v-model="item.value"></el-input>
                  </el-col>
                  <el-col :span="4">
                    <el-button type="primary" size="mini" icon="el-icon-plus" circle @click="addNewPostProcessing()"></el-button>
                    <el-button type="danger" size="mini" icon="el-icon-delete" circle v-on:click="postProcessing.splice(index,1)"></el-button>
                  </el-col>
                </el-row>
              </div>

            </el-tab-pane>
            <el-tab-pane label="断言" name="fix">
              <div class="interface-edit-tabs">
                <el-button type="primary" size="mini" icon="el-icon-plus" @click="addNewAssertion()">添加</el-button>
                <el-row v-for="(item,index) in assertions" :key="index">
                  <el-col :span="6">
                    <el-select placeholder="断言类型" v-model="item.type">
                      <el-option label="respAssertion / 响应数据断言" value="respAssertion"></el-option>
                      <el-option label="jsonAssertion / 返回结果断言" value="jsonAssertion"></el-option>
                      <el-option label="duraAssertion / 响应时间断言" value="duraAssertion"></el-option>
                    </el-select>
                  </el-col>
                  <el-col :span="7">
                    <el-input placeholder="断言路径，格式：$.code" v-model="item.key"></el-input>
                  </el-col>
                  <el-col :span="7">
                    <el-input placeholder="value" v-model="item.value"></el-input>
                  </el-col>
                  <el-col :span="4">
                    <el-button type="primary" size="mini" icon="el-icon-plus" circle @click="addNewAssertion()"></el-button>
                    <el-button type="danger" size="mini" icon="el-icon-delete" circle v-on:click="assertions.splice(index,1)"></el-button>
                  </el-col>
                </el-row>
              </div>

            </el-tab-pane>
          </el-tabs>

        </div>

      </div>

    </div>

    <div>
      <h3 class="api-title" style="margin-top: 1.5rem;"> Response</h3>

      <div class="api-debug-response">

        <el-tabs v-model="activeResponseName">
          <el-tab-pane label="请求信息" name="first">
            <myEditor v-model="request.url" language='dockerfile' title="response"> </myEditor>

          </el-tab-pane>
          <el-tab-pane label="返回结果" name="second">
            <div class="api-debug-response-span">
              <span>Status：<span style="color:rgb(23, 179, 163)">{{response.code}}</span> </span>
              <span>Time： <span style="color:rgb(23, 179, 163);margin-left: 10px;">{{response.loadTime}} s</span></span>
              <span>Size：<span style="color:rgb(23, 179, 163);margin-left: 10px;">{{response.size}} B</span></span>
            </div>
            <myEditor v-model="response.responseData" language='dockerfile' title="response"> </myEditor>
          </el-tab-pane>
          <el-tab-pane label="请求Header" name="third">
            <div class="api-debug-response-span">
              <span>Size：<span style="color:rgb(23, 179, 163);margin-left: 10px;">{{response.headerSize}} B</span></span>
            </div>
            <myEditor v-model="response.responseHeader" language='dockerfile' title="response"> </myEditor>
          </el-tab-pane>

          <el-tab-pane label="断言结果" name="four">
            <myEditor v-model="response.assertionResult" language='dockerfile' title="response"> </myEditor>
          </el-tab-pane>
        </el-tabs>

      </div>
    </div>

    <div style="text-align:center;margin-top: 60px;position: fixed;bottom:0;width:55%;padding-bottom: 15px">
      <el-button type="primary" size="small" @click="addCaseStep()"><i class="el-icon-plus"></i>添加</el-button>
      <el-button type="success" size="small" @click="updateCase()"><i class="el-icon-refresh"></i>更新</el-button>
      <el-button type="warning" size="small" @click="executeDebugCase()" :loading="debugLoading"><i class="el-icon-caret-right"></i>调试</el-button>
      <!-- <el-button type="danger" size="small" @click="expectParamObjectCopy(assertion)"><i class="el-icon-finished"></i>生成断言</el-button> -->
    </div>

  </div>
</template>

<script>
import { isEmpty } from '@/utils/baseUtil'
import myEditor from '@/components/editor/editor.vue'
export default {
  data () {
    return {
      activeName: 'first',
      activeResponseName: 'second',
      projectId: null,
      debugLoading: false,

      //用例信息
      caseForm: {},
      //用例步骤信息
      caseStepForm: {},
      //分组列表
      groupList: [],
      //接口信息
      apiForm: {},
      //接口列表
      apiList: [],

      //环境列表
      envList: {
        list: [],
      },

      request: {},
      response: {},

      parameters: [],
      headers: [],
      preProcessing: [],
      postProcessing: [],
      assertions: [],

    }
  },

  components: {
    myEditor
  },
  methods: {




    //获取接口分组
    getGroup (projectId) {
      this.data = []
      this.$http({
        url: this.$http.adornUrl('/aitesting/group/listByProjectId'),
        method: 'get',
        params: {
          projectId: projectId,
          groupType: 0,
        }
      }).then(({ data }) => {
        if (data.code == 0) {
          this.groupList = data.list
        } else {
          this.$message({
            message: data.msg,
            type: 'warning'
          });
        }
      })
    },

    //查询分组下接口
    handleChange (groupId) {
      this.$http({
        url: this.$http.adornUrl('/aitesting/api/getByCondition'),
        method: 'get',
        params: {
          projectId: this.projectId,
          groupId: groupId,
          interfaceId: '',
          keyword: '',
          pageIndex: 1,
          pageSize: 10000,
        }
      }).then(({ data }) => {
        if (data.code == 0) {
          this.apiList = data.page.apis
        } else {
          this.$message({
            message: data.msg,
            type: 'warning'
          });
        }
      })
    },

    //查询接口信息
    handleChangeApi (apiId) {
      this.apiList.forEach((item, index, arr) => {
        if (item.id == apiId) {
          this.apiForm = JSON.parse(JSON.stringify(item))
          this.parameters = JSON.parse(item.queryParam)
          this.headers = JSON.parse(item.requestHeader)
        }
      })
    },

    //查询环境
    getEnvList () {
      this.envList.list = []
      this.$http({
        url: this.$http.adornUrl('/aitesting/enviroment/listBy'),
        method: 'get',
        params: {
          'projectId': this.projectId,
          'pageIndex': 1,
          'pageSize': 1000,
          'id': '',
          'keyword': '',
        }
      }).then(({ data }) => {
        if (data.code == 0) {
          this.envList.list = data.page.envs
          console.log(this.envList.list)

        } else {
          this.$message({ message: data.msg, type: 'warning' });
        }
      })
    },

    //添加用例
    addCaseStep () {
      if (isEmpty(this.caseStepForm.envId)) {
        this.$message({ message: "请选择环境！", type: 'warning' });
        return
      }
      let apiCaseStepForm = this.updateCaseStepForm()
      this.$http({
        url: this.$http.adornUrl('/aitesting/testStep/save'),
        method: 'post',
        data: apiCaseStepForm,
      }).then(({ data }) => {
        if (data.code == 0) {
          this.$message({
            type: 'success',
            message: data.msg,
          });
          this.$emit("getCaseSteps", this.caseForm.id)
        } else {
          this.$message({
            type: 'warning',
            message: data.msg,
          });
        }
      })
    },

    //数据转化
    updateCaseStepForm () {
      this.caseStepForm.testCaseId = this.caseForm.id
      this.caseStepForm.stepOrder = 1
      this.caseStepForm.stepOrder = 1
      this.caseStepForm.apiId = this.apiForm.id
      this.caseStepForm.projectId = this.apiForm.projectId
      this.caseStepForm.groupId = this.apiForm.groupId
      this.caseStepForm.requestBodyType = this.apiForm.requestBodyType

      //请求参数
      this.caseStepForm.requestBody = this.listToJsonNew(this.parameters)
      //请求头
      this.caseStepForm.requestHeader = this.listToJsonNew(this.headers)
      //请求前置
      this.caseStepForm.preProcessing = this.listToJsonNew(this.preProcessing)
      //请求后置
      this.caseStepForm.postProcessing = this.listToJsonNew(this.postProcessing)
      //断言
      this.caseStepForm.assertion = JSON.stringify(this.generateAssertions(this.assertions))
      this.caseStepForm.otherConfiguration = JSON.stringify({})
      return this.caseStepForm
    },

















    //获取单用例信息
    getCaseById (id) {
      console.log(id)
      this.$http({
        url: this.$http.adornUrl('/aitesting/apiTestCase/get'),
        method: 'get',
        params: {
          'id': id,
        }
      }).then(({ data }) => {
        if (data.code == 0) {
          this.caseForm = data.data
          this.parameters = this.jsonToListTo(JSON.parse(data.data.queryParam))
          this.headers = this.jsonToListTo(JSON.parse(data.data.requestHeader))
          this.preProcessing = this.jsonToListTo(JSON.parse(data.data.preProcessing))
          this.postProcessings = this.jsonToListTo(JSON.parse(data.data.postProcessing))

          this.jsonToList(data.data.assertion)
          //   this.assertion = this.jsonToListTo(JSON.parse(data.data.assertion))
        } else {
          this.$message({ message: data.msg, type: 'warning' });
        }
      })
    },



    //更新用例
    updateCase () {
      if (isEmpty(this.caseForm.envId)) {
        this.$message({ message: "请选择环境！", type: 'warning' });
        return
      }
      let apiCaseForm = this.updateCaseForm()

      if (isEmpty(this.caseForm.id) || this.caseForm.id == 0 || this.caseForm.id == '0') {
        this.$message({ message: "用例编号为空，无法更新！", type: 'warning' });
        return
      }
      apiCaseForm.status = 1
      this.$http({
        url: this.$http.adornUrl('/aitesting/apiTestCase/update'),
        method: 'post',
        data: apiCaseForm,
      }).then(({ data }) => {
        if (data.code == 0) {
          this.$message({
            type: 'success',
            message: data.msg,
          });
          this.$emit("getCaseSteps", this.apiForm.id)
        } else {
          this.$message({
            type: 'warning',
            message: data.msg,
          });
        }
      })
    },

    //执行用例
    executeDebugCase () {
      this.debugLoading = true
      let testCaseInfo = {}
      let testStepList = []
      let testStep = {}

      //步骤id
      testStep.id = this.caseForm.id
      //步骤名
      testStep.name = this.caseForm.name
      //接口id
      testStep.apiId = this.apiForm.id
      //环境id
      testStep.envId = this.caseForm.envId
      //协议类型
      testStep.protocol = this.apiForm.protocol
      //环境
      this.envList.list.forEach((item, index, arr) => {
        if (item.id == this.caseForm.envId) {
          testStep.domain = item.host
          testStep.port = item.port
        }
      })
      //请求方法
      testStep.method = this.apiForm.method
      //请求路径
      testStep.path = this.apiForm.path
      //步骤类型
      testStep.type = 1
      //步骤编码
      testStep.encode = ''
      //请求参数
      testStep.query = ""
      testStep.postDataType = 'form'
      testStep.httpHeader = JSON.parse(this.listToJsonNew(this.headers))
      testStep.body = this.listToJsonNew(this.parameters)
      testStep.preProcessing = JSON.parse(this.listToJsonNew(this.preProcessing))
      testStep.postProcessing = JSON.parse(this.listToJsonNew(this.postProcessing))

      testStep.otherConfiguration = {}
      //断言
      testStep.assertions = this.generateAssertions(this.assertions)

      testStepList.push(testStep)
      this.$http({
        url: this.$http.adornUrl('/aitesting/apiTestCase/run'),
        method: 'post',
        data: { testCaseInfo, testStepList },
      }).then(({ data }) => {
        if (data.code == 0) {
          this.response = JSON.parse(JSON.stringify(data.result))
          if (this.isJson(this.response.responseData)) {
            this.response.responseData = JSON.stringify(JSON.parse(this.response.responseData), null, 2)
          }
          this.response.assertionResult = JSON.stringify(this.response.assertionResult, null, 2)
          console.log(this.response.assertionResult)
          this.debugLoading = false
        } else {
          this.$message({
            type: 'warning',
            message: data.msg,
          });
          this.debugLoading = false
        }
      })
    },





    //生成断言，必须服务端格式
    generateAssertions (assertion) {
      let duraAssertion = {}
      let jsonAssertion = []
      let respAssertion = []
      if (isEmpty(assertion)) {
        return { duraAssertion, respAssertion, jsonAssertion }
      }
      for (let i = 0; i < assertion.length; i++) {
        if (assertion[i].type == 'duraAssertion') {
          duraAssertion = { name: '响应时间断言', duration: assertion[i].value }

        } else if (assertion[i].type == 'jsonAssertion') {
          let exepect = { name: '返回结果断言', jsonPath: assertion[i].key, jsonValidation: false, exceptValue: assertion[i].value }
          jsonAssertion.push(exepect)

        } else if (assertion[i].type == 'respAssertion') { }
      }
      return { duraAssertion, respAssertion, jsonAssertion }
    },


    //list转json  获取的时候使用
    listToJsonNew (params) {
      var param_str = "";
      var obj = {};
      if (isEmpty(params)) {
        params = [];
      }
      for (var i = 0; i < params.length; i++) {
        var params_value = isEmpty(params[i].value) ? '' : params[i].value.replace(/\\"/g, '\"');
        var params_name = params[i].name;
        obj[params_name] = params_value;
      }
      return JSON.stringify(obj);
    },

    //将json的key的value赋值给list的值
    jsonToListTo (json) {
      var list = [];
      for (var key in json) {
        list.push({
          name: key,
          value: (typeof json[key] == 'string') ? json[key].replace(/\"/g, '\\"') : JSON.stringify(json[key]).replace(/\"/g, '\\"')
          //   value: json[key]
          //    value: json[key].replace(/\"/g, '\\"')
        });
      }
      return list;
    },

    //断言使用，将json转list
    jsonToList (str) {
      this.assertions = []
      if (isEmpty(str)) {
        return
      }
      let assertion = JSON.parse(str)
      for (let i in assertion) {
        if (i == 'jsonAssertion') {
          for (let j in assertion[i]) {
            let obj = {
              name: '返回结果断言',
              type: i,
              key: assertion[i][j]['jsonPath'],
              value: assertion[i][j]['exceptValue']
            }
            this.assertions.push(obj)
          }
        } else if (i == 'duraAssertion') {
          let obj = {
            name: '响应时间断言',
            type: i,
            key: '',
            value: assertion[i]['duration']
          }
          this.assertions.push(obj)

        } else if (i == 'respAssertion') {
        }


      }




    },


    //新增参数
    addNewParams () {
      if (isEmpty(this.parameters)) {
        this.headersparameters = []
      }
      this.parameters.push({ name: "", value: '' })
    },

    //添加请求头
    addNewHeaders () {
      if (isEmpty(this.headers)) {
        this.parameters = []
      }
      this.headers.push({ name: "", value: '' })
    },

    //添加前置处理
    addNewPreProcessing () {
      if (isEmpty(this.preProcessing)) {
        this.preProcessing = [];
      }
      this.preProcessing.push({ name: "", value: "" });
    },

    //添加后置处理
    addNewPostProcessing () {
      if (isEmpty(this.postProcessing)) {
        this.postProcessing = [];
      }
      this.postProcessing.push({ name: "", value: "" });
    },

    //添加断言
    addNewAssertion () {
      if (isEmpty(this.assertions)) {
        this.assertions = [];
      }
      this.assertions.push({
        type: "duraAssertion",
        key: "",
        value: ""
      });
    },

    //判断是否json
    isJson (str) {
      try {
        JSON.parse(str)
        return true
      } catch (e) {
        return false
      }

    },
  },


  watch: {
    //获取接口信息
    '$store.state.api.caseInfoForm' () {
      this.caseForm = JSON.parse(JSON.stringify(this.$store.state.api.caseInfoForm))
      console.log(this.caseForm)
    }
  },

  activated () {
    this.projectId = this.$store.state.api.projectId
    this.getEnvList()
    this.getGroup(this.projectId)
  },

}
</script>

<style scoped>
.case-edit >>> .el-button--mini.is-circle {
  padding: 7px;
}

.api-bottom-button {
  text-align: center;
  margin-top: 60px;
  position: fixed;
  bottom: 0;
  padding-bottom: 15px;
  margin-left: 220px;
}

.case-edit .interface-edit-tabs .el-col {
  padding-right: 6px;
}

.case-edit .interface-tab {
  border: 1px solid rgb(220, 223, 230);
  border-radius: 4px;
  background: rgb(247 247 247 / 67%);
}

.case-edit .interface-tab-in {
  margin-left: 10px;
  min-height: 100px;
}

.case-edit .interface-edit-tabs .el-row {
  padding-bottom: 8px;
}

.case-edit .interface-debug-p {
  font-size: 14px;
  font-weight: 700;
  margin-bottom: 1px;
}

.case-edit >>> .api-debug-select {
  width: 130px;
}

.case-edit-api-info >>> .el-select {
  display: contents;
}

.case-edit >>> .api-debug-select-1 {
  width: 180px;
}

.case-edit >>> .el-input-group__append {
  color: #fff;
  background-color: #17b3a3;
  border-color: #17b3a3;
}

.interface-edit-tabs >>> .el-select {
  display: contents;
}

.api-debug-response-span {
  font-size: 14px;
  float: right;
  padding-bottom: 5px;
}

.api-title {
  margin-bottom: 1.5rem;
}
</style>